package com.caesar.dao;

import com.caesar.utils.JDBCUtil;

import java.lang.reflect.Field;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;

/**
 * @author caesar
 * @date 2025/7/29
 * @Description:抽象增删改查功能的父类
 * @apiNote
 */
public class BaseDao {

    /**
     * 执行增删改
     * @param sql：要执行的SQL语句
     * @param args：按照顺序为占位符所赋的值
     * @return：返回受影响的行数
     */
    public int update(String sql, Object... args) {
        Connection connection = null;
        PreparedStatement statement = null;
        int result = 0;

        try {
            connection = JDBCUtil.getConnection();
            statement = connection.prepareStatement(sql);
            //为占位符赋值，要求args是按照顺序为占位符赋值的数据
            for (int i = 0; i < args.length; i++) {
                statement.setObject(i + 1, args[i]);
            }
            result = statement.executeUpdate();
        } catch (SQLException e) {
            throw new RuntimeException(e);
        } finally {
            JDBCUtil.close(connection, statement, null);
        }
        return result;
    }

    /**
     * 查询多条数据转换为实体类类型的List集合
     * @param sql：要执行的SQL语句
     * @param clazz：查询的数据要转换的类型的Class对象
     * @param args：按照顺序为占位符所赋的值
     * @return：查询的数据所转换的实体类类型的List集合
     * @param <T>：实体类的类型
     */
    public <T> List<T> getBeanList(String sql, Class<T> clazz, Object... args) {
        Connection connection = null;
        PreparedStatement statement = null;
        ResultSet resultSet = null;
        List<T> list = new ArrayList<>();

        try {
            connection = JDBCUtil.getConnection();
            statement = connection.prepareStatement(sql);
            for (int i = 0; i < args.length; i++) {
                statement.setObject(i + 1, args[i]);
            }
            resultSet = statement.executeQuery();
            //获取结果集的元数据
            ResultSetMetaData resultSetMetaData = resultSet.getMetaData();
            //获取列数
            int columnCount = resultSetMetaData.getColumnCount();
            //遍历结果集
            while (resultSet.next()) {
                T t = clazz.newInstance();
                for (int i = 1; i <= columnCount; i++) {
                    //根据列数获取字段名，无法获取别名
                    //String columnName = resultSetMetaData.getColumnName(i);
                    //根据列数获取字段名或别名
                    String columnName = resultSetMetaData.getColumnLabel(i);
                    //将字段名columnName作为要转换的类型中的属性名，获取属性对象
                    Field field = clazz.getDeclaredField(columnName);
                    //暴力反射（忽略field所对应属性的访问权限）
                    field.setAccessible(true);
                    //为field属性赋值
                    field.set(t, resultSet.getObject(i));
                }
                list.add(t);
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            JDBCUtil.close(connection, statement, resultSet);
        }
        return list;
    }

    /**
     * 查询一条数据转换为实体类类型的对象
     * @param sql：要执行的SQL语句
     * @param clazz：查询的数据要转换的类型的Class对象
     * @param args：按照顺序为占位符所赋的值
     * @return：查询的数据所转换的实体类类型的对象
     * @param <T>：实体类的类型
     */
    public <T> T getBean(String sql, Class<T> clazz, Object... args) {
        Connection connection = null;
        PreparedStatement statement = null;
        ResultSet resultSet = null;
        T t = null;

        try {
            connection = JDBCUtil.getConnection();
            statement = connection.prepareStatement(sql);
            for (int i = 0; i < args.length; i++) {
                statement.setObject(i + 1, args[i]);
            }
            resultSet = statement.executeQuery();
            //获取结果集的元数据
            ResultSetMetaData resultSetMetaData = resultSet.getMetaData();
            //获取列数
            int columnCount = resultSetMetaData.getColumnCount();
            //遍历结果集
            if (resultSet.next()) {
                t = clazz.newInstance();
                for (int i = 1; i <= columnCount; i++) {
                    //根据列数获取字段名，无法获取别名
                    //String columnName = resultSetMetaData.getColumnName(i);
                    //根据列数获取字段名或别名
                    String columnName = resultSetMetaData.getColumnLabel(i);
                    //将字段名columnName作为要转换的类型中的属性名，获取属性对象
                    Field field = clazz.getDeclaredField(columnName);
                    //暴力反射（忽略field所对应属性的访问权限）
                    field.setAccessible(true);
                    //为field属性赋值
                    field.set(t, resultSet.getObject(i));
                }
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            JDBCUtil.close(connection, statement, resultSet);
        }
        return t;
    }
    /**
     * args:按照顺序为占位符所赋的值
     * */
    public Object getSingleData(String sql, Object... args) {
        Connection connection = null;
        PreparedStatement statement = null;
        ResultSet resultSet = null;
        Object result = null;

        try {
            connection = JDBCUtil.getConnection();
            statement = connection.prepareStatement(sql);
            for (int i = 0; i < args.length; i++) {
                statement.setObject(i + 1, args[i]);
            }
            resultSet = statement.executeQuery();//执行查询
            //单行单列结果读取
            if (resultSet.next()) {
                result = resultSet.getObject(1);
            }
        } catch (SQLException e) {
            throw new RuntimeException(e);
        } finally {
            JDBCUtil.close(connection, statement, resultSet);
        }
        return result;
    }
}
